﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Web.UI.WebControls;
using System.Web.UI;

namespace Exaction.UI.WebControl
{
    public class TextBoxWithCounter : System.Web.UI.WebControls.WebControl, INamingContainer
    {
        #region Private Variables

        private TextBox tbMainTexBox;
        private TextBox tbCounter;
        private System.Web.UI.WebControls.WebControl wcContainer;
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the text.
        /// </summary>
        /// <value>The text.</value>
        [Description("Gets or sets the text content of the text box"),
        Category("Appearance"),
        Bindable(true),
        DefaultValue("")
        ]
        public string Text
        {
            get
            {
                this.EnsureChildControls();
                if (tbMainTexBox.Text == null)
                {
                    return String.Empty;
                }
                return tbMainTexBox.Text;
            }
            set
            {
                this.EnsureChildControls();
                tbMainTexBox.Text = value;
            }
        }
        /// <summary>
        /// Sets a value indicating whether this instance is read only.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is read only; otherwise, <c>false</c>.
        /// </value>
        public bool IsReadOnly
        {
            set
            {
                this.EnsureChildControls();
                tbMainTexBox.ReadOnly = value;
            }
        }
        #endregion

        #region Constructor
        /// <summary>
        /// Initializes a new instance of the <see cref="TextBoxWithCounter"/> class.
        /// </summary>
        /// <param name="maxLength">Length of the max.</param>
        /// <param name="rows">The rows.</param>
        /// <param name="cols">The cols.</param>
        /// <param name="mode">The mode.</param>
        /// <param name="cssClass">The CSS class.</param>
        /// <param name="width">The width.</param>
        public TextBoxWithCounter(int maxLength, int rows, int cols, TextBoxMode mode)
            : base()
        {
            tbMainTexBox = new TextBox();
            tbMainTexBox.MaxLength = maxLength;
            tbMainTexBox.Rows = rows;
            tbMainTexBox.Columns = cols;
            tbMainTexBox.TextMode = mode;
            tbMainTexBox.ID = "_textBoxWithCounter" + this.ID;
            tbCounter = new TextBox();
            tbCounter.ID = "_controlCounterPart" + this.ID;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="TextBoxWithCounter"/> class.
        /// </summary>
        public TextBoxWithCounter()
            : base()
        {
            tbMainTexBox = new TextBox();
            tbMainTexBox.ID = "_textBoxWithCounter" + this.ID;

            tbCounter = new TextBox();
            tbCounter.ID = "_controlCounterPart" + this.ID;
        }
        #endregion

        #region Overridden Methods
        /// <summary>
        /// Restores view-state information from a previous request that was saved with the <see cref="M:System.Web.UI.WebControls.WebControl.SaveViewState"/> method.
        /// </summary>
        /// <param name="savedState">An object that represents the control state to restore.</param>
        protected override void LoadViewState(object savedState)
        {
            base.LoadViewState(savedState);
            if (this.ViewState["-1Saved"] != null && (Boolean)this.ViewState["-1Saved"])
            { // not really sure why I have to do this
                this.Text = string.Empty;
            }
        }
        /// <summary>
        /// Called by the ASP.NET page framework to notify server controls that use composition-based implementation to create any child controls they contain in preparation for posting back or rendering.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId = "System.Web.UI.ITextControl.set_Text(System.String)", Justification = "Literal contains HTML elements. Globalisation is not required.")]
        protected override void CreateChildControls()
        {
            wcContainer = new System.Web.UI.WebControls.WebControl(HtmlTextWriterTag.Span);
            wcContainer.ID = "Container";
            this.Controls.Add(wcContainer);
            wcContainer.Controls.Add(tbMainTexBox);

            Literal lt = new Literal();
            lt.Text = "<br /><font size=\"1\">(Maximum characters: " + tbMainTexBox.MaxLength + ")<br \\>You have ";
            wcContainer.Controls.Add(lt);

            tbCounter.Columns = 5;
            tbCounter.ReadOnly = true;
            wcContainer.Controls.Add(tbCounter);

            Literal lt2 = new Literal();
            lt2.Text = " characters left.</font>";
            wcContainer.Controls.Add(lt2);
            string js = "function limitText(limitField, limitCount, limitNum) {if (limitField.value.length > limitNum) {limitField.value = limitField.value.substring(0, limitNum);} else {limitCount.value = limitNum - limitField.value.length; }}";
            this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "textboxwithcounter", js,true);
        }
        /// <summary>
        /// Renders the control to the specified HTML writer.
        /// </summary>
        /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the control content.</param>
        override protected void Render(HtmlTextWriter writer)
        {
            this.EnsureChildControls();
            wcContainer.RenderControl(writer);
        }
        /// <summary>
        /// Raises the <see cref="E:System.Web.UI.Control.PreRender"/> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"/> object that contains the event data.</param>
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            tbCounter.Text = (tbMainTexBox.MaxLength - Text.Length).ToString(System.Globalization.CultureInfo.CurrentCulture);

            // Wire up the events
            tbMainTexBox.Attributes.Add("onKeyDown", "limitText(" + tbMainTexBox.UniqueID.Replace("$", "_") + "," + tbCounter.UniqueID.Replace("$", "_") + "," + tbMainTexBox.MaxLength + ");");
            tbMainTexBox.Attributes.Add("onKeyUp", "limitText(" + tbMainTexBox.UniqueID.Replace("$", "_") + "," + tbCounter.UniqueID.Replace("$", "_") + "," + tbMainTexBox.MaxLength + ");");
            tbMainTexBox.Attributes.Add("onBlur", "limitText(" + tbMainTexBox.UniqueID.Replace("$", "_") + "," + tbCounter.UniqueID.Replace("$", "_") + "," + tbMainTexBox.MaxLength + ");");

        }
        #endregion

        #region Designer Support
        /// <summary>
        /// The text area of the DatePicker.
        /// </summary>
        /// <remarks>This is used by the designer.</remarks>
        protected internal TextBox TextControl
        {
            get
            {
                EnsureChildControls();
                return tbMainTexBox;
            }
        }
        /// <summary>
        /// The container control of ComboBox's controls.
        /// </summary>
        /// <remarks>
        /// This is used by the designer.
        /// </remarks>
        protected internal System.Web.UI.WebControls.WebControl ContainerControl
        {
            get
            {
                EnsureChildControls();
                return wcContainer;
            }
        }
        #endregion
    }
}
